/**
 * 根据指定的格式化字符串返回当前时间
 * @param {Date} date 日期类型
 * @param {string} format 格式化字符串
 * @returns 
 */
function formatDate(date, format = 'yyyy-MM-dd HH:mm') {
  const d = date;
  if(date == null) return null;
  // 格式映射表
  const map = {
    'yyyy': d.getFullYear(),
    'MM': String(d.getMonth() + 1).padStart(2, '0'),
    'dd': String(d.getDate()).padStart(2, '0'),
    'HH': String(d.getHours()).padStart(2, '0'),
    'mm': String(d.getMinutes()).padStart(2, '0'),
    'ss': String(d.getSeconds()).padStart(2, '0'),
  };

  // 替换格式占位符
  return format.replace(/(yyyy|MM|dd|HH|mm|ss)/g, (match) => map[match]);
}

/** 时间转化为描距当前多久的描述
 * @param {string} dateString 形如 2025-01-21 9:24:41 的字符串
 * @returns 刚刚/N分钟/N小时/N天/N周/N月/N年 前的描述字符串
 */
function formatDateDiff(dateString) {
  const date = new Date(dateString)
  const now = new Date()
  const diff = Math.abs(now - date)
  const second = 1000
  const minute = second * 60
  const hour = minute * 60
  const day = hour * 24
  const week = day * 7
  const month = day * 30
  const year = day * 365
  const years = Math.floor(diff / year)
  const months = Math.floor(diff / month)
  const weeks = Math.floor((diff % month) / week)
  const days = Math.floor((diff % week) / day)
  const hours = Math.floor((diff % day) / hour)
  const minutes = Math.floor((diff % hour) / minute)
  if (diff < minute) {
    return '刚刚'
  } else if (diff < hour) {
    return `${minutes} 分钟前`
  } else if (diff < day) {
    return `${hours} 小时前`
  } else if (diff < week) {
    return `${days} 天前`
  } else if (diff < month) {
    return `${weeks} 周前`
  } else if (diff < year) {
    return `${months} 个月前`
  } else {
    return `${years} 年前`
  }
}

/**
 * 用于格式化日期版本为描述字符串
 * @param {string} 形如 2025-01-21 的字符串 
 * @returns 
 */
function formatDateVersionToDesc(dateString) {
  const date = new Date(dateString);
  const now = new Date();

  // 获取某日的0点时间
  const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
  const today = startOfDay(now);
  const yesterday = today - 86400000; // 一天的毫秒数
  const dateStart = startOfDay(date);

  // 判断今天、昨天
  if (dateStart === today) return '今天';
  if (dateStart === yesterday) return '昨天';

  // 处理时间差（防止未来时间）
  const diff = now - date;
  if (diff < 0) return '刚刚';

  const day = 86400000;
  const days = Math.floor(diff / day);

  if (days < 7) return `${days} 天前`;

  const weeks = Math.floor(days / 7);
  if (days < 30) return `${weeks} 周前`;

  const months = Math.floor(days / 30);
  if (diff < day * 365) return `${months} 个月前`;

  const years = Math.floor(days / 365);
  return `${years} 年前`;
}
// 压缩字符串函数
function gzip(data) {
  var uint8Array = pako.gzip(data);
  var binaryString = String.fromCharCode.apply(null, uint8Array);
  return btoa(binaryString);
}
/** 解压字符串函数
 * 
 * 依赖 pako
 * @param {string} compressedData 压缩过的字符串
 * @returns 解压后的字符串
 */ 
function deGzip(compressedData) {
  var binaryString = atob(compressedData)
  var uint8Array = new Uint8Array(binaryString.length)
  for (var i = 0; i < binaryString.length; i++) {
    uint8Array[i] = binaryString.charCodeAt(i)
  }
  return pako.ungzip(uint8Array, { to: 'string' })
}
/** 全局提示函数
 * 
 * 依赖 sweetalert2
 * @param {string} message 消息内容
 * @param {string} type 消息类型，success, error, warning, info, question
 */
function createAlert(message, type, time = 3000) {
  const Toast = Swal.mixin({
    toast: true,
    position: 'top',
    showConfirmButton: false,
    timer: time,
    timerProgressBar: true,
    didOpen: (toast) => {
      toast.onmouseenter = Swal.stopTimer
      toast.onmouseleave = Swal.resumeTimer
    },
  })
  Toast.fire({
    icon: type,
    title: message,
  })
}

/**
 * 增强版 copyRichText，支持 Base64 图片
 * @param {string} content 富文本内容或 Base64 图片
 * @param {Object} options 配置选项；type|txt/html/image；altText|图片的纯文本
 * @returns {Promise<boolean>} 复制是否成功
 */
async function copyRichText(content, options = {}) {
  try {
    options == options || {type:"txt"};
    options.type == options.type || "txt";

    if(options?.type === "image"){
      // 判断是否为 Base64 图片
      if (isBase64Image(content)) {
        return await copyBase64ImageAsHTML(content, options.altText || 'Image');
      }
    }else if(options?.type === "html"){
      // 普通富文本处理
      if (navigator.clipboard && window.ClipboardItem) {
        return await copyWithClipboardAPI(content, options.type);
      }
      return copyWithExecCommand(content, options.type);
    } else {
      // 普通富文本处理
      if (navigator.clipboard && window.ClipboardItem) {
        return await copyWithClipboardAPI(content, options.type);
      }
      return copyWithExecCommand(content, options.type);
    }
  } catch (error) {
    console.error('复制失败:', error);
    return false;
  }
}

/**
 * 判断是否为 Base64 图片
 */
function isBase64Image(str) {
  // 检查是否为 Base64 图片格式
  const base64ImagePattern = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/;
  const dataUrlPattern = /^data:image\/[a-zA-Z]+;base64,/;
  
  return dataUrlPattern.test(str) || 
         (str.length > 50 && base64ImagePattern.test(str));
}

/**
 * 将 Base64 图片作为 HTML 复制
 */
async function copyBase64ImageAsHTML(base64Image, altText) {
  try {
    // 构造完整的 data URL
    const dataUrl = base64Image.startsWith('data:') 
      ? base64Image 
      : `data:image/png;base64,${base64Image}`;
    
    // 创建 HTML 内容
    const htmlContent = `<img src="${dataUrl}" alt="${altText}" />`;
    const plainText = altText;
    
    if (navigator.clipboard && window.ClipboardItem) {
      const htmlBlob = new Blob([htmlContent], { type: 'text/html' });
      const textBlob = new Blob([plainText], { type: 'text/plain' });
      
      await navigator.clipboard.write([
        new ClipboardItem({
          'text/html': htmlBlob,
          'text/plain': textBlob
        })
      ]);
      
      return true;
    }
    
    // 回退方法
    return copyWithExecCommand(htmlContent, 'html');
  } catch (error) {
    console.error('复制图片失败:', error);
    return false;
  }
}

/**
 * 使用 Clipboard API 复制
 */
async function copyWithClipboardAPI(content, type = 'text') {
  if(type === 'html'){
    const htmlBlob = new Blob([content], { type: 'text/html' });
    const textContent = new DOMParser().parseFromString(content, 'text/html').body.textContent || '';
    const textBlob = new Blob([textContent], { type: 'text/plain' });
    
    await navigator.clipboard.write([
      new ClipboardItem({
        'text/html': htmlBlob,
        'text/plain': textBlob
      })
    ]);
  }else{
    const blob = new Blob([content], { type: 'text/plain' });
    await navigator.clipboard.writeText(blob);
  }
  return true;
}

/**
 * 使用传统方法复制
 */
function copyWithExecCommand(content, type = 'text') {
  const textarea = document.createElement('div');
  textarea.style.position = 'fixed';
  textarea.style.left = '-9999px';
  textarea.style.top = '-9999px';
  textarea.style.opacity = '0';
  if(type === 'html'){
    textarea.innerHTML = content;
  }else{
    textarea.textContent = content;
  }
  document.body.appendChild(textarea);
  
  const range = document.createRange();
  range.selectNodeContents(textarea);
  
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  
  try {
    const successful = document.execCommand('copy');
    selection.removeAllRanges();
    return successful;
  } finally {
    document.body.removeChild(textarea);
  }
}

/**
 * 复制富文本
 * @param {string} richText 富文本内容
 */
/*function copyRichText(richText) {
  const tempContainer = document.createElement('div')
  tempContainer.innerHTML = richText
  document.body.appendChild(tempContainer)

  const range = document.createRange()
  range.selectNode(tempContainer)

  const selection = window.getSelection()
  selection.removeAllRanges()
  selection.addRange(range)

  document.execCommand('copy')
  document.body.removeChild(tempContainer)
}*/
/**
 * 获取URL的参数
 * @param {string} url 
 * @returns 包含url参数键的对象
 */
function getQueryParams(url) {
  // 创建一个URL对象
  const urlObj = new URL(url)
  // 获取查询字符串
  const queryString = urlObj.search
  // 初始化一个空对象来存储参数
  const params = {}
  // 分割查询字符串为键值对
  queryString
    .substring(1)
    .split('&')
    .forEach((param) => {
      // 分割每个键值对
      const [key, value] = param.split('=')
      // 将键值对添加到params对象中
      params[key] = decodeURIComponent(value)
    })
  return params
}
/**
 * 根据html内容返回一个dom对象
 * @param {string} html 
 * @returns dom对象
 */
function createDivByHtml(html) {
  var range = document.createRange()
  var fragment = range.createContextualFragment(html)
  return fragment.firstChild
}